﻿using System.Linq;
using Xenta.Entities;
using Xenta.Utils;

namespace Xenta.Operations
{
    /// <summary>
    /// Represents the translation create operation base.
    /// </summary>
    /// <typeparam name="TTranslation">The type of translation.</typeparam>
    /// <typeparam name="THolder">The type of translation holder.</typeparam>
    public abstract class CreateTranslation<TTranslation, THolder> : 
        CreateAuditable<TTranslation> where TTranslation : 
        TranslationEntity<THolder> where THolder :
        Entity
    {
        #region Properties

        /// <summary>
        /// Gets or sets the holder identifier.
        /// </summary>
        public int HolderID
        {
            get;
            set;
        }

        /// <summary>
        /// Gets or sets the language identifier.
        /// </summary>
        public int LanguageID
        {
            get;
            set;
        }

        #endregion

        #region Utilities

        protected override void Construct(IUnitOfWork uow, TTranslation entity)
        {
            base.Construct(uow, entity);

            entity.Holder = uow.Execute(new GetEntity<THolder>
            {
                ThrowsException = true,
                EntityID = HolderID
            }).Result;
            entity.Language = uow.Execute(new GetLanguage
            {
                ThrowsException = true,
                EntityID = LanguageID
            }).Result;
        }

        #endregion
    }

    /// <summary>
    /// Represents the translation update operation base.
    /// </summary>
    /// <typeparam name="TTranslation">The type of translation.</typeparam>
    /// <typeparam name="THolder">The type of translation holder.</typeparam>
    public abstract class UpdateTranslation<TTranslation, THolder> : 
        UpdateAuditable<TTranslation> where TTranslation :
        TranslationEntity<THolder> where THolder :
        Entity
    {
        #region Properties

        /// <summary>
        /// Gets or sets the language identifier.
        /// </summary>
        public int LanguageID
        {
            get;
            set;
        }

        #endregion

        #region Utilities

        protected override void Revise(IUnitOfWork uow, TTranslation entity)
        {
            base.Revise(uow, entity);

            entity.Language = uow.Execute(new GetLanguage
            {
                ThrowsException = true,
                EntityID = LanguageID
            }).Result;
        }

        #endregion
    }

    /// <summary>
    /// Represents the translation save operation base.
    /// </summary>
    /// <typeparam name="TTranslation">The type of translation.</typeparam>
    /// <typeparam name="THolder">The type of translation holder.</typeparam>
    public abstract class SaveTranslation<TTranslation, THolder> : 
        Operation<TTranslation> where TTranslation :
        TranslationEntity<THolder> where THolder :
        Entity
    {
        #region Properties

        /// <summary>
        /// Gets or sets the holder identifier.
        /// </summary>
        public int HolderID
        {
            get;
            set;
        }

        /// <summary>
        /// Gets or sets the language identifier.
        /// </summary>
        public int LanguageID
        {
            get;
            set;
        }

        #endregion
    }

    /// <summary>
    /// Deletes the translation.
    /// </summary>
    /// <typeparam name="TTranslation">The type of translation.</typeparam>
    /// <typeparam name="THolder">The type of translation holder.</typeparam>
    public class DeleteTranlsation<TTranslation, THolder> : 
        DeleteEntity<TTranslation> where TTranslation : 
        TranslationEntity<THolder> where THolder :
        Entity
    {
    }

    /// <summary>
    /// Gets the translation by identifier.
    /// </summary>
    /// <typeparam name="TTranslation">The type of translation.</typeparam>
    /// <typeparam name="THolder">The type of translation holder.</typeparam>
    public class GetTranlsation<TTranslation, THolder> : 
        GetEntity<TTranslation> where TTranslation : 
        TranslationEntity<THolder> where THolder :
        Entity
    {
    }

    /// <summary>
    /// Gets the translation by language.
    /// </summary>
    /// <typeparam name="TTranslation">The type of translation.</typeparam>
    /// <typeparam name="THolder">The type of translation holder.</typeparam>
    public class GetTranlsationByLanguage<TTranslation, THolder> : 
        QueryEntity<TTranslation> where TTranslation : 
        TranslationEntity<THolder> where THolder :
        Entity
    {
        #region Properties

        /// <summary>
        /// Gets or sets the holder identifier.
        /// </summary>
        public int HolderID
        {
            get;
            set;
        }

        /// <summary>
        /// Gets or sets the language identifier.
        /// </summary>
        public int LanguageID
        {
            get;
            set;
        }

        #endregion

        #region Utilities

        protected override IQueryable<TTranslation> Build(IUnitOfWork uow, IQueryable<TTranslation> query)
        {
            return base.Build(uow, query).Where(x => 
                x.Holder.EntityID == HolderID && 
                x.Language.EntityID == LanguageID);
        }

        #endregion
    }
}
